package io.onsense.universe.format;

import io.onsense.universe.ArrayHelper;

import java.util.Arrays;
import java.util.Locale;
import java.util.NoSuchElementException;
import java.util.Objects;

/**
 * @author Koen Rooijmans
 */
public enum BarcodeType {
    CODE11("CODE11", "CODE-11", "CODE 11"),
    CODE16K("CODE16K", "CODE-16K", "CODE 16K"),
    CODE25("CODE25", "CODE-25", "CODE 25"),
    CODE2OF5("CODE2OF5", "CODE-2OF5", "CODE 2OF5", "CODE 2 OF 5"),
    CODE32("CODE32", "CODE-32", "CODE 32"),
    CODE39("CODE39", "CODE-39", "CODE 39"),
    CODE39EXT("CODE39EXT", "CODE-39-EXT", "CODE 39 EXT", "CODE39 EXT", "CODE-39 EXT"),
    CODE39EXTENDED("CODE39EXTENDED", "CODE-39-EXTENDED", "CODE 39 EXTENDED", "CODE39 EXTENDED", "CODE-39 EXTENDED"),
    EXTENDEDCODE39("EXTENDEDCODE39", "EXTENDED-CODE-39", "EXTENDED CODE 39", "EXTENDED CODE39", "EXTENDED CODE-39"),
    CODE49("CODE49", "CODE-49", "CODE 49"),
    CODE93("CODE93", "CODE-93", "CODE 93"),
    CODE93EXT("CODE93EXT", "CODE-93-EXT", "CODE 93 EXT", "CODE93 EXT", "CODE-93 EXT"),
    CODE93EXTENDED("CODE93EXTENDED", "CODE-93-EXTENDED", "CODE 93 EXTENDED", "CODE93 EXTENDED", "CODE-93 EXTENDED"),
    EXTENDEDCODE93("EXTENDEDCODE93", "EXTENDED-CODE-93", "EXTENDED CODE 93", "EXTENDED CODE93", "EXTENDED CODE-93"),
    CODE128("CODE128", "CODE-128", "CODE 128"),
    CODEONE("CODEONE", "CODE-ONE", "CODE ONE"),
    EAN2("EAN2", "EAN-2", "EAN 2"),
    EAN5("EAN5", "EAN-5", "EAN 5"),
    EAN8("EAN8", "EAN-8", "EAN 8"),
    EAN13("EAN13", "EAN-13", "EAN 13"),
    EAN14("EAN14", "EAN-14", "EAN 14"),
    EAN128("EAN128", "EAN-128", "EAN 128"),
    EANBOOKLAND("EANBOOKLAND", "EAN-BOOKLAND", "EAN BOOKLAND"),
    JAN13("JAN13", "JAN-13", "JAN 13"),
    ITF14("ITF14", "ITF-14", "ITF 14"),
    MSI10("MSI10", "MSI-10", "MSI 10"),
    MSI11("MSI11", "MSI-11", "MSI 11"),
    MSI1010("MSI1010", "MSI-1010", "MSI 1010"),
    MSI1110("MSI1110", "MSI-1110", "MSI 1110"),
    UPCA("UPCA", "UPC-A", "UPC A"),
    UPCACOMPOSITE("UPCACOMPOSITE", "UPC-A-COMPOSITE", "UPC A COMPOSITE", "UPCA COMPOSITE", "UPC-A COMPOSITE"),
    UPCE("UPCE", "UPC-E", "UPC E"),
    UPCECOMPOSITE("UPCECOMPOSITE", "UPC-E-COMPOSITE", "UPC E COMPOSITE", "UPCE COMPOSITE", "UPC-E COMPOSITE"),
    PDF417("PDF417", "PDF-417", "PDF 417"),
    BC412("BC412", "BC-412", "BC 412"),
    RSS14("RSS14", "RSS-14", "RSS 14"),
    RSSEXPANDED("RSSEXPANDED", "RSS-EXPANDED", "RSS EXPANDED"),
    SSCC18("SSCC18", "SSCC-18", "SSCC 18"),
    GS114("GS114", "GS1-14", "GS1 14"),
    GS1128("GS1128", "GS1-128", "GS1 128"),
    GS1128COMPOSITE("GS1128COMPOSITE", "GS1-128-COMPOSITE", "GS1 128 COMPOSITE", "GS1128 COMPOSITE", "GS1-128 COMPOSITE"),
    GS1CC("GS1CC", "GS1-CC", "GS1 CC"),
    GS1QRCODE("GS1QRCODE", "GS1-QR-CODE", "GS1 QR CODE", "GS1QR CODE", "GS1-QR CODE"),
    QRCODE("QRCODE", "QR-CODE", "QR CODE"),
    SHOTCODE("SHOTCODE", "SHOT-CODE", "SHOT CODE"),
    CODABLOCK("CODABLOCK", "CODA-BLOCK", "CODA BLOCK"),
    CODABAR("CODABAR", "CODA-BAR", "CODA BAR"),
    CHANNELCODE("CHANNELCODE", "CHANNEL-CODE", "CHANNEL CODE"),
    AZTECCODE("AZTECCODE", "AZTEC-CODE", "AZTEC CODE"),
    AZTECRUNES("AZTECRUNES", "AZTEC-RUNES", "AZTEC RUNES"),
    DATABAR("DATABAR", "DATA-BAR", "DATA BAR"),
    DOTCODE("DOTCODE", "DOT-CODE", "DOT CODE"),
    DATAMATRIX("DATAMATRIX", "DATA-MATRIX", "DATA MATRIX"),
    MAXICODE("MAXICODE", "MAXI-CODE", "MAXI CODE"),
    PHARMACODE("PHARMACODE", "PHARMA-CODE", "PHARMA CODE"),
    LOGMARS("LOGMARS", "LOG-MARS", "LOG MARS"),
    POSTNET("POSTNET", "POST-NET", "POST NET"),

    UPC("UPC"),
    EAN("EAN"),
    QR("QR"),
    ISBN("ISBN"),
    ISMN("ISMN"),
    ISSN("ISSN"),
    SISAC("SISAC"),
    ITF("ITF"),
    AZTEC("AZTEC"),
    MSI("MSI"),

    AUSPOST("AUSPOST"),
    AZTECCODECOMPACT("AZTECCODECOMPACT"),
    AZTECRUNE("AZTECRUNE"),
    CODABLOCKF("CODABLOCKF"),
    COOP2OF5("COOP2OF5"),
    DAFT("DAFT"),
    DATABAREXPANDED("DATABAREXPANDED"),
    DATABAREXPANDEDCOMPOSITE("DATABAREXPANDEDCOMPOSITE"),
    DATABAREXPANDEDSTACKED("DATABAREXPANDEDSTACKED"),
    DATABAREXPANDEDSTACKEDCOMPOSITE("DATABAREXPANDEDSTACKEDCOMPOSITE"),
    DATABARLIMITED("DATABARLIMITED"),
    DATABARLIMITEDCOMPOSITE("DATABARLIMITEDCOMPOSITE"),
    DATABAROMNI("DATABAROMNI"),
    DATABAROMNICOMPOSITE("DATABAROMNICOMPOSITE"),
    DATABARSTACKED("DATABARSTACKED"),
    DATABARSTACKEDCOMPOSITE("DATABARSTACKEDCOMPOSITE"),
    DATABARSTACKEDOMNI("DATABARSTACKEDOMNI"),
    DATABARSTACKEDOMNICOMPOSITE("DATABARSTACKEDOMNICOMPOSITE"),
    DATABARTRUNCATED("DATABARTRUNCATED"),
    DATABARTRUNCATEDCOMPOSITE("DATABARTRUNCATEDCOMPOSITE"),
    DATALOGIC2OF5("DATALOGIC2OF5"),
    DATAMATRIXRECTANGULAR("DATAMATRIXRECTANGULAR"),
    EAN13COMPOSITE("EAN13COMPOSITE"),
    EAN8COMPOSITE("EAN8COMPOSITE"),
    FLATTERMARKEN("FLATTERMARKEN"),
    GS1DATAMATRIX("GS1DATAMATRIX"),
    GS1DATAMATRIXRECTANGULAR("GS1DATAMATRIXRECTANGULAR"),
    GS1NORTHAMERICANCOUPON("GS1NORTHAMERICANCOUPON"),
    HANXIN("HANXIN"),
    HIBCAZTECCODE("HIBCAZTECCODE"),
    HIBCCODABLOCKF("HIBCCODABLOCKF"),
    HIBCCODE128("HIBCCODE128"),
    HIBCCODE39("HIBCCODE39"),
    HIBCDATAMATRIX("HIBCDATAMATRIX"),
    HIBCDATAMATRIXRECTANGULAR("HIBCDATAMATRIXRECTANGULAR"),
    HIBCMICROPDF417("HIBCMICROPDF417"),
    HIBCPDF417("HIBCPDF417"),
    HIBCQRCODE("HIBCQRCODE"),
    IATA2OF5("IATA2OF5"),
    IDENTCODE("IDENTCODE"),
    INDUSTRIAL2OF5("INDUSTRIAL2OF5"),
    INTERLEAVED2OF5("INTERLEAVED2OF5"),
    JAPANPOST("JAPANPOST"),
    KIX("KIX"),
    LEITCODE("LEITCODE"),
    MATRIX2OF5("MATRIX2OF5"),
    MICROPDF417("MICROPDF417"),
    MICROQRCODE("MICROQRCODE"),
    ONECODE("ONECODE"),
    PDF417COMPACT("PDF417COMPACT"),
    PHARMACODE2("PHARMACODE2"),
    PLANET("PLANET"),
    PLESSEY("PLESSEY"),
    POSICODE("POSICODE"),
    PZN("PZN"),
    RATIONALIZEDCODABAR("RATIONALIZEDCODABAR"),
    RAW("RAW"),
    ROYALMAIL("ROYALMAIL"),
    SYMBOL("SYMBOL"),
    TELEPEN("TELEPEN"),
    TELEPENNUMERIC("TELEPENNUMERIC"),
    ULTRACODE("ULTRACODE");

    final String[] aliases;

    BarcodeType(String alias, String... aliases) {
        this.aliases = ArrayHelper.prepend(alias, aliases);
    }

    public static BarcodeType lookup(String alias) {
        for (BarcodeType barcodeType : values()) {
            if (Arrays.stream(barcodeType.getAliases())
                    .anyMatch(s -> Objects.equals(s, alias.toUpperCase(Locale.ENGLISH)))) {
                return barcodeType;
            }
        }
        throw new NoSuchElementException("No barcode found for alias " + alias);
    }

    public static boolean isBarcode(String alias) {
        try {
            final BarcodeType lookup = lookup(alias);
            return lookup != null;
        } catch (NoSuchElementException ignored) {
            return false;
        }
    }

    protected String[] getAliases() {
        return aliases;
    }
}
